function cfunc = convones(f, cnum, w)
% convones  - convoles a function with a number of consecutive ones
%
% FORMAT:       cfunc = convones(f, cnum [, w])
%
% Input fields:
%
%       f           function to convolve
%       cnum        number of consecutive ones to use
%       w           if 1x1 true, weight (divide by number of samples)
%
% Output fields:
%
%       cfunc       ones-convolved function
%
% See also conv

% Version:  v0.7f
% Build:    8111619
% Date:     Nov-16 2008, 7:32 PM CET
% Author:   Jochen Weber, SCAN Unit, Columbia University, NYC, NY, USA
% URL/Info: http://wiki.brainvoyager.com/BVQXtools

% argument check
if nargin < 2 || ...
   ~isa(f, 'double') || ...
    numel(f) ~= max(size(f)) || ...
   ~isa(cnum, 'double') || ...
    numel(cnum) ~= 1 || ...
    isinf(cnum) || ...
    isnan(cnum) || ...
    cnum < 1 || ...
    cnum ~= fix(cnum)
    error( ...
        'BVQXtools:BadArgument', ...
        'Bad or missing first argument.' ...
    );
end

% special case: cnum == 1
if cnum == 1
    cfunc = f;
    return;
end

% get size and dim of f
fn = numel(f);
[fd{1:2}] = max(size(f));
f = f(:);

% produce output and intermediate vector
lf = fn + cnum - 1;
cfunc = zeros(lf, 1);
cimed = [f; zeros(cnum - 1, 1)];

% weight
if nargin > 2 && ...
    islogical(w) && ...
    numel(w) == 1 && ...
    w
    wfunc = convones(ones(fn, 1), cnum);
else
    wfunc = [];
end

% continue as long as cnum is not 0 !
cpos = 0;
mfac = fix(cnum / 2);
cfac = 1;
while cnum > 0
    if mod(cnum, 2)
        cfunc = cfunc + ...
            [zeros(cpos, 1); cimed(1:lf-cpos)];
        cpos = cpos + cfac;
    end
    if cfac > mfac
        break;
    end
    cimed = [cimed(1:lf-cfac) ; zeros(cfac, 1)] + ...
            [zeros(cfac, 1) ; cimed(1:lf-cfac)];
    cfac = cfac * 2;
    cnum = fix(cnum / 2);
end

% weight now
if ~isempty(wfunc)
    cfunc = cfunc ./ wfunc;
end

% shift to f dim
if fd{2} > 1
    cfunc = shiftdim(cfunc, 1 - fd{2});
end
